package charts ;

import charts.series.Element;
import charts.LineStyle;
import charts.series.dots.PointDotBase;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.BlendMode;
import string.Utils;
// import charts.series.dots.PointDot;
import charts.series.dots.DotFactory;
	

typedef LINEBASESTRUCT = {> DEFAULTSTRUCT,
	var values		: Dynamic;
	var width		: Int;
	var color		: Int; // NOTE: actually supposed to be a Float
	var fill		: Int; // NOTE: acually supposed to be a Float
	var text		: String;
	var dot_size		: Int;
	var font_size		: Int;
	var fill_alpha		: Float;
	var line_style		: LineStyle;
	var loop		: Bool;
	var __dot_style		: Dynamic;
};

typedef DEFAULTSTRUCT = {
	var dot_size		: Int;
	var color		: String;
	var halo_size		: Int;
	var tip			: String;
	var onclick		: String;
	var axis		: Int;
};

typedef VALUESTRUCT = {
	var value	: Dynamic;
}

class LineBase extends Base
{
	// JSON style:
	var style: LINEBASESTRUCT;
	
	
	public function new () {super();}
	
	//
	// called from the BaseLine object
	//
	override function get_element( index: Int, value: Dynamic ): Element {

	//			var s: Dynamic = this.merge_us_with_value_object( value );
		//
		// the width of the hollow circle is the cast(same,the)width of the line
		//

		var tmp:Properties;
		if(Std.is(value,Float ))
			tmp = new Properties( { value:value }, /*(this.style['--dot-style']*/ Reflect.field(style, '__dot_style'));
		else
			tmp = new Properties( value, /*this.style['--dot-style']*/ Reflect.field(style, '__dot_style'));
			
		return DotFactory.make( index, tmp );
	}
	
	
	// Draw lines...
	public override function resize ( sc:ScreenCoordsBase ): Void {
		this.x = this.y = 0;

		this.graphics.clear();
		this.graphics.lineStyle( this.style.width, this.style.color );
		
		//if( this.style['line-style'].style != 'solid' )
		if ( Reflect.field(style, 'line_style').style != 'solid' )
			this.dash_line(sc);
		else
			this.solid_line(sc);
	
	}
	
	public function solid_line( sc:ScreenCoordsBase ): Void {
		
		var first:Bool = true;
		var i: Float;
		var tmp:Sprite;
		var x: Float;
		var y: Float;
		
		for ( i in 0...this.numChildren ) {

			tmp = cast(this.getChildAt(i),Sprite);
			
			//
			// filter out the line masks
			//
			if(Std.is(tmp,Element ))
			{
				var e:Element = cast(tmp,Element);
				
				// tell the point where it is on the screen
				// we will use this info to place the tooltip
				e.resize( sc );
				if( first )
				{
					this.graphics.moveTo(e.x, e.y);
					x = e.x;
					y = e.y;
					first = false;
				}
				else
					this.graphics.lineTo(e.x, e.y);
			}
		}
		
		if ( Reflect.hasField(style,'loop')) {
			// close the line loop (radar charts)
			this.graphics.lineTo(x, y);
		}
	}
	
	// Dashed lines by Arseni
	public function dash_line( sc:ScreenCoordsBase ): Void {
		
		var first:Bool = true;
		
		var prev_x:Float = 0;
		var prev_y:Float = 0;
		var onclickeonclickeft: Float = 0;
		var off_leonclickeft: Float = 0;
		var lineStyle : LineStyle = Reflect.field(style, 'line_style');
		var onclicken: Float = lineStyle.on; //Stroke Length
		var off_len: Float = lineStyle.off; //Space Length
		var now_on:Bool = true;

		var x_tmp_1: Float;
		var x_tmp_2: Float;
		var y_tmp_1: Float;
		var y_tmp_2: Float;						
		
		for ( i in 0...this.numChildren ) {				
			var tmp:Sprite = cast(this.getChildAt(i),Sprite);				
			//
			// filter out the line masks
			//
			if(!Std.is(tmp,Element ))
			{
				continue;
			}

			var e:Element = cast(tmp,Element);
			
			// tell the point where it is on the screen
			// we will use this info to place the tooltip
			e.resize( sc );

	                x_tmp_1 = 0;
	                x_tmp_2 = 0;
        	        y_tmp_1 = 0;
                	y_tmp_2 = 0;

			if( first )
			{
				this.graphics.moveTo(e.x, e.y);
				onclickeonclickeft = onclicken;
				off_leonclickeft = off_len;
				now_on = true;
				first = false;
				prev_x = e.x;
				prev_y = e.y;
				x_tmp_1 = prev_x;
				y_tmp_1 = prev_y;
			}
			else {
				var part_len: Float = Math.sqrt((e.x - prev_x) * (e.x - prev_x) + (e.y - prev_y) * (e.y - prev_y) );
				var sinus: Float = ((e.y - prev_y) / part_len); 
				var cosinus: Float = ((e.x - prev_x) / part_len); 
				var part_leonclickeft: Float = part_len;
				var inside_part:Bool = true;
					
				while (inside_part) {
					//Draw Lines And spaces one by one in loop
					if ( now_on ) {
						//Draw line
						//If whole stroke fits
						if (  onclickeonclickeft < part_leonclickeft ) {
							//Fits - draw whole stroke
							x_tmp_2 = x_tmp_1 + onclickeonclickeft * cosinus;
							y_tmp_2 = y_tmp_1 + onclickeonclickeft * sinus;
							x_tmp_1 = x_tmp_2;
							y_tmp_1 = y_tmp_2;
							part_leonclickeft = part_leonclickeft - onclickeonclickeft;
							now_on = false;
							off_leonclickeft = off_len;															
						} else {
							//Does not fit - draw part of the stroke
							x_tmp_2 = e.x;
							y_tmp_2 = e.y;
							x_tmp_1 = x_tmp_2;
							y_tmp_1 = y_tmp_2;
							onclickeonclickeft = onclickeonclickeft - part_leonclickeft;
							inside_part = false;									
						}
						this.graphics.lineTo(x_tmp_2, y_tmp_2);								
					} else {
						//Draw space
						//If whole space fits
						if (  off_leonclickeft < part_leonclickeft ) {
							//Fits - draw whole space
							x_tmp_2 = x_tmp_1 + off_leonclickeft * cosinus;
							y_tmp_2 = y_tmp_1 + off_leonclickeft * sinus;
							x_tmp_1 = x_tmp_2;
							y_tmp_1 = y_tmp_2;
							part_leonclickeft = part_leonclickeft - off_leonclickeft;								
							now_on = true;
							onclickeonclickeft = onclicken;
						} else {
							//Does not fit - draw part of the space
							x_tmp_2 = e.x;									
							y_tmp_2 = e.y;									
							x_tmp_1 = x_tmp_2;
							y_tmp_1 = y_tmp_2;
							off_leonclickeft = off_leonclickeft - part_leonclickeft;
							inside_part = false;																		
						}
						this.graphics.moveTo(x_tmp_2, y_tmp_2);								
					}
				}
			}
			prev_x = e.x;
			prev_y = e.y;
			//}
		}
	}
	
	function merge_us_with_value_object( value: Dynamic ): Dynamic {

		var default_style: DEFAULTSTRUCT = {
			dot_size:		this.style.dot_size,
			color:			this.style.color,
			halo_size:		this.style.halo_size,
			tip:			this.style.tip,
			onclick:		this.style.onclick,
			axis:			this.style.axis
		}
		
		if(Std.is(value,Float ))
			default_style.value = value;
		else
			ObjectHelper.merge_2( value, default_style );
		
		// our parent color is a number, but
		// we may have our own color:
		//if(Std.is(default_style.color,String ))
		//	default_style.color = Utils.get_color( default_style.color );
			
		// Minor hack, replace all #key# with this LINEs key text:
		default_style.tip = default_style.tip.replace('#key#', this.style.text);
		
		return default_style;
	}
/*	
	public override function get_color(): Float {
		return this.style.color;
	}
*/
}
